﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace IRC.IRepairClouds.DataLayer
{
    public static class DateTimeExtensions
    {
        public static DateTime ToClientDate(this DateTime date)
        {
            return date.ToClient(false);
        }
        public static DateTime FromClientDate(this DateTime date)
        {
            return date.FromClient(false);
        }
        public static DateTime ToClientTime(this DateTime date)
        {
            return date.ToClient(true);
        }
        public static DateTime FromClientTime(this DateTime date)
        {
            return date.FromClient(true);
        }
        public static DateTime ToClient(this DateTime date, bool timeZoneShift)
        {
            if (timeZoneShift)
            {
                var tz = Cache.CacheManager.Users.Current.TimeZone.Cached.TimeZone;
                bool toUtc = false;
                if (date.Kind == DateTimeKind.Utc)
                {
                    date = date.ToLocalTime();
                    toUtc = true;
                }
                date = TimeZoneInfo.ConvertTime(date, TimeZoneInfo.Local, tz);
                if (toUtc)
                    date = date.ToUniversalTime();
            }
            return date;
            //return date.ToUniversalTime();
        }
        public static DateTime FromClient(this DateTime date, bool timeZoneShift)
        {
            if (timeZoneShift)
            {
                var tz = Cache.CacheManager.Users.Current.TimeZone.Cached.TimeZone;
                bool toUtc = false;
                if (date.Kind == DateTimeKind.Utc)
                {
                    date = date.ToLocalTime();
                    toUtc = true;
                }
                if (date.Kind == DateTimeKind.Local && tz != TimeZoneInfo.Local)
                    date = new DateTime(date.Ticks, DateTimeKind.Unspecified);
                date = TimeZoneInfo.ConvertTime(date, tz, TimeZoneInfo.Local);
                if (toUtc)
                    date = date.ToUniversalTime();
            }
            return date;
            //return date.ToLocalTime();
        }

        public static DateTime? ToClientDate(this DateTime? date)
        {
            return date.ToClient(false);
        }
        public static DateTime? FromClientDate(this DateTime? date)
        {
            return date.FromClient(false);
        }
        public static DateTime? ToClientTime(this DateTime? date)
        {
            return date.ToClient(true);
        }
        public static DateTime? FromClientTime(this DateTime? date)
        {
            return date.FromClient(true);
        }
        public static DateTime? ToClient(this DateTime? date, bool timeZoneShift)
        {
            if (date == null)
                return null;
            return date.Value.ToClient(timeZoneShift);
        }
        public static DateTime? FromClient(this DateTime? date, bool timeZoneShift)
        {
            if (date == null)
                return null;
            return date.Value.FromClient(timeZoneShift);
        }



        private const string DateTimeFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.fffffff";

        public static string ToClientDateStr(this DateTime date)
        {
            return date.ToClientStr(false);
        }
        public static string ToClientDateStr(this DateTime? date)
        {
            return date.ToClientStr(false);
        }
        public static DateTime? FromClientDateStr(this string date)
        {
            return date.FromClientStr(false);
        }
        public static string ToClientTimeStr(this DateTime date)
        {
            return date.ToClientStr(true);
        }
        public static string ToClientTimeStr(this DateTime? date)
        {
            return date.ToClientStr(true);
        }
        public static DateTime? FromClientTimeStr(this string date)
        {
            return date.FromClientStr(true);
        }
        public static string ToClientStr(this DateTime date, bool timeZoneShift)
        {
            DateTime d = date.ToClient(timeZoneShift);
            return "@Date(" + d.ToString(DateTimeFormat) + ")@";
        }
        public static string ToClientStr(this DateTime? date, bool timeZoneShift)
        {
            if (date == null)
                return null;
            return date.Value.ToClientStr(timeZoneShift);
        }
        public static DateTime? FromClientStr(this string date, bool timeZoneShift)
        {
            if (string.IsNullOrEmpty(date))
                return null;

            var m = Regex.Match(date, @"^@Date\((\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{7})\)@$");
            if (m.Success && m.Groups.Count >= 2 && m.Groups[1].Success)
                date = m.Groups[1].Value;

            var d = DateTime.ParseExact(date, DateTimeFormat, null, System.Globalization.DateTimeStyles.NoCurrentDateDefault);
            return d.FromClient(timeZoneShift);
        }
    }
}
